#include "fifo.h"

uint8_t fifo_com1_rx[BUFF_Size];

Fifo_t fifo_com1;

/*******************************************************
How to used it:
Fifo_t ll_fifo;
uint8_t fifo_buff[20];
FifoInit( &ll_fifo, fifo_buff, 20);
FifoTest(&ll_fifo,12);
********************************************************/


/**
 *****************************************************************************
 ** \brief 队列指偏移
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval void                                 
 *****************************************************************************/
static uint16_t FifoNext( Fifo_t *fifo, uint16_t index )
{
    return ( index + 1 ) % fifo->Size;
}

/**
 *****************************************************************************
 ** \brief 队列初始化
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval void                                
 *****************************************************************************/

void FifoInit( Fifo_t *fifo, uint8_t *buffer, uint16_t size )
{
    fifo->Begin = 0;
    fifo->End = 0;
    fifo->Data = buffer;
    fifo->Size = size;
}

/**
 ************************************************************
 ** \brief 队列插入一个数据
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval  void                                 
 ***********************************************************/
void FifoPush( Fifo_t *fifo, uint8_t data )
{
    fifo->End = FifoNext( fifo, fifo->End );
    fifo->Data[fifo->End] = data;
}

/**
 ***********************************************************
 ** \brief 队列出一个数据
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval  数据                                
 ***********************************************************/
uint8_t FifoPop( Fifo_t *fifo )
{
    uint8_t data = fifo->Data[FifoNext( fifo, fifo->Begin )];

    fifo->Begin = FifoNext( fifo, fifo->Begin );
    return data;
}

/**
 ***********************************************************
 ** \brief  队列清空
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval  1: 空   0:不空                                  
 ***********************************************************/
void FifoFlush( Fifo_t *fifo )
{
    fifo->Begin = 0;
    fifo->End = 0;
}

/**
 ************************************************************
 ** \brief 判断队列是否为空
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval  1: 空   0:不空                                  
 ***********************************************************/
bool IsFifoEmpty( Fifo_t *fifo )
{
    return ( fifo->Begin == fifo->End );
}

/**
 ************************************************************
 ** \brief 判断队列是否为满
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval  1: 满  0:未满                               
 ************************************************************/
bool IsFifoFull( Fifo_t *fifo )
{
    return ( FifoNext( fifo, fifo->End ) == fifo->Begin );
}

/**
 ************************************************************
 ** \brief 计算队列有效数据存储深度
 **
 **
 ** \param 1:fifo 队列块 
 ** 
 ** \retval  void                                  
 ***********************************************************/

uint16_t FifoDepth( Fifo_t *fifo )
{
    return ( fifo->End - fifo->Begin );
}


/**
 ************************************************************
 ** \brief  队列测试
 **
 **
 ** \param 1:fifo 队列块  2:size 数据长度
 ** 
 ** \retval  void                                  
 ************************************************************/
void FifoTest(Fifo_t *fifo, uint16_t size)
{
	for(int i = 0; i < size; i++)
	{
		FifoPush(fifo, i);
	}
	
	for(int i = 0; i < size; i++)
	{
		printf("\r\nPop data = %d",FifoPop(fifo));
	}
}


/**
 ************************************************************
 ** \brief 向队列中插入N个数据
 **
 **
 ** \param 1 : fifo 队列块,  2*data 数据指针  3：数据长度
 ** 
 ** \retval  状态码                                  
 *************************************************************/
enum_fifo en_Queue( Fifo_t *fifo, uint8_t *data, uint16_t lentghBytes)
{
 	 uint16_t  remain_lentgh =0;
 	 uint16_t   i = 0;
	 remain_lentgh = BUFF_Size - FifoDepth(fifo);	
	 if(fifo == NULL)
	 {
	    return  ERR_ADDR;
	 }
	 else if(lentghBytes > remain_lentgh)
	 {
	    return  ERR_FIFO_SPACE_NOT_ENOUGH;         
	 }
	 else if(IsFifoFull(fifo))
	 {
	    return  ERR_FIFO_FULL; 
	 }
	 else
	 {
		for(i = 0; i < lentghBytes; i++)
		{
	      FifoPush(fifo,*(data+i));	
		}			
	 }
	 return OK;	
}


/**
 *************************************************************
 ** \brief 从队列中取出N个数据
 **
 **
 ** \param 1 : fifo 队列块,  2*data 数据指针  3：数据长度
 ** 
 ** \retval  状态码                                  
 *************************************************************/
enum_fifo de_Queue(Fifo_t *fifo, uint8_t *data, uint16_t lentghBytes)
{
 	 uint16_t  remain_lentgh =0;
 	 uint16_t   i=0;
	 remain_lentgh = FifoDepth(fifo);	
	 if(fifo == NULL)
	 {
	    return  ERR_ADDR;
	 }
	 else if(lentghBytes > remain_lentgh)
	 {
	    return  ERR_FIFO_LEN_NOT_ENOUGH;  
	        
	 }
	 else if(IsFifoEmpty(fifo))
	 {
	    return  ERR_FIFO_EMPTY; 
	 }
	 else
	 {
		for(i=0; i<lentghBytes; i++)
		{
	        *(data+i) = FifoPop(fifo);	 
		}			
	 }
	 return OK;	
}


